using Baula.Testing.Common;
using Baula.TextGen.ActiveTemplating.Tokenizer;
using Baula.TextGen.ActiveTemplating.Tokenizer.Tokens;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Baula.TextGen.ActiveTemplating.Tests.Tokenizer
{
    [TestClass]
    public class TemplateTokenizerTests
    {
        [TestMethod]
        public void Null()
        {
            AssertTokens(null, new EofToken());
        }

        [TestMethod]
        public void EmptyString()
        {
            AssertTokens(string.Empty, new EofToken());
        }

        [TestMethod]
        public void Literal()
        {
            AssertTokens("This is just literal text.",
                         new LiteralToken("This is just literal text."),
                         new EofToken());
        }

        [TestMethod]
        public void InlineExpression()
        {
            AssertTokens("{JustThisExpression}",
                         new InlineExpressionToken("JustThisExpression"),
                         new EofToken());
        }

        [TestMethod]
        public void InlineExpression_InlineExpression()
        {
            AssertTokens("{FirstExpression}{SecondExpression}",
                         new InlineExpressionToken("FirstExpression"),
                         new InlineExpressionToken("SecondExpression"),
                         new EofToken());
        }

        [TestMethod]
        public void InlineExpression_Literal()
        {
            AssertTokens("{AnExpression} ALiteral",
                         new InlineExpressionToken("AnExpression"),
                         new LiteralToken(" ALiteral"),
                         new EofToken());
        }

        [TestMethod]
        public void InlineExpression_Literal_InlineExpression()
        {
            AssertTokens("{FirstExpression} ALiteral {SecondExpression}",
                         new InlineExpressionToken("FirstExpression"),
                         new LiteralToken(" ALiteral "),
                         new InlineExpressionToken("SecondExpression"),
                         new EofToken());
        }

        [TestMethod]
        public void Literal_InlineExpression()
        {
            AssertTokens("ALiteral {AnExpression}",
                         new LiteralToken("ALiteral "),
                         new InlineExpressionToken("AnExpression"),
                         new EofToken());
        }

        [TestMethod]
        public void Literal_InlineExpression_Literal()
        {
            AssertTokens("First Literal {AnExpression} Second Literal",
                         new LiteralToken("First Literal "),
                         new InlineExpressionToken("AnExpression"),
                         new LiteralToken(" Second Literal"),
                         new EofToken());
        }

        [TestMethod]
        public void SingleLineBlockExpression()
        {
            AssertTokens("{{Some single line block expression}}",
                         new BlockExpressionToken("Some single line block expression"),
                         new EofToken());
        }

        [TestMethod]
        public void BlockExpressionContainingInlineExpressionPrefix()
        {
            AssertTokens("{{This is a block expression containing this: { <-- that's a inline expression prefix.}}",
                         new BlockExpressionToken("This is a block expression containing this: { <-- that's a inline expression prefix."),
                         new EofToken());
        }

        [TestMethod]
        public void InlineExpressionContainingBlockExpressionPrefix()
        {
            AssertTokens("{This is a block expression containing this: {{ <-- that's a block expression prefix.}",
                         new InlineExpressionToken("This is a block expression containing this: {{ <-- that's a block expression prefix."),
                         new EofToken());
        }

        private void AssertTokens(string template, params IToken[] expectedTokens)
        {
            var actualTokens = new TemplateTokenizer(template).Tokenize();
            actualTokens.AssertEqual(expectedTokens);
        }
    }
}